package com.mobi.Survey.map;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.os.AsyncTask;

import com.google.android.gms.maps.model.LatLng;
import com.mobi.Survey.adapters.CustomAdapterUserList;
import com.mobi.Survey.lib.activities.AbstractScreen;
import com.mobi.Survey.lib.activities.Messages;
import com.mobi.Survey.lib.utils.Helper;

public class SearchTask extends AsyncTask<Integer, Integer, Integer> {

	private AbstractScreen screen;
	private SearchContext searchContext;
	private SearchComplete searchComplete;

	public SearchComplete getSearchComplete() {
		return searchComplete;
	}

	public void setSearchComplete(SearchComplete searchComplete) {
		this.searchComplete = searchComplete;
	}

	public SearchTask(AbstractScreen screen, SearchContext searchContext) {
		this.screen = screen;
		this.searchContext = searchContext;

	}

	private static final int NO_BUSINESS = 0;

	private static final int SWITCH_SCREEN = 1;

	private static final int NO_INTERNET_CONNECTION = 2;

	private static final int CONNECT_ERROR = 3;
	private static final int DEFAULT = 4;

	ProgressDialog progressDialog = null;
	List<MapMarker> mapMarkers;

	protected Integer doInBackground(Integer... params) {
		if (isCancelled()) {
			return DEFAULT;
		}
		if (Helper.isNetworkAvailable(this.screen.getApplicationContext())) {

			try {

				StringBuilder queryParam = new StringBuilder(40);

				queryParam.append("country="
						+ URLEncoder.encode(searchContext.country));

				queryParam.append("&zip=" + searchContext.zip);

				queryParam.append("&state="
						+ URLEncoder.encode(searchContext.state));

				queryParam.append("&city="
						+ URLEncoder.encode(searchContext.city));

				queryParam.append("&keyword="
						+ URLEncoder.encode(searchContext.keyword));
				queryParam.append("&startIndex=" + searchContext.startIndex);
				queryParam.append("&numOfRows=" + searchContext.pageSize);

				String surveyUrl = this.screen.getString(R.string.serach_ws)
						+ queryParam.toString();

				publishProgress(30);

				InputStream surveyResponse = Helper
						.performGetOperationI(surveyUrl);

				Map<MapMarker, Integer> markersWithDuplicateCount = new HashMap<MapMarker, Integer>();
				mapMarkers = new MapSurveysJsonParser(
						this.screen.getApplicationContext()).parseForMap(
						surveyResponse, markersWithDuplicateCount);

				if (mapMarkers.size() == 0) {
					return NO_BUSINESS;
				} else {
					searchContext.totaCount = mapMarkers.get(0)
							.getTotalPoints();
				}

				calculateAlternatePointsForMarkers(markersWithDuplicateCount);

				return SWITCH_SCREEN;

			} catch (IOException e) {
				return CONNECT_ERROR;
			} catch (Exception e) {

				return NO_BUSINESS;
			}

		} else {
			return NO_INTERNET_CONNECTION;
		}

	}

	private void calculateAlternatePointsForMarkers(
			Map<MapMarker, Integer> duplicateWithCount) {
		for (MapMarker duplicteMarker : duplicateWithCount.keySet()) {
			Integer duplicatesOfMarker = duplicateWithCount.get(duplicteMarker);

			double lon = Helper.toDouble(duplicteMarker.getLongitude());
			double lat = Helper.toDouble(duplicteMarker.getLatitude());
			double radiusMin = 0.2;
			double radiusInKm = 0.3;
			if (duplicatesOfMarker <= 10) {
				radiusInKm = 0.04;
				radiusMin = 0.01;
			} else if (duplicatesOfMarker <= 50) {
				radiusInKm = 0.2;
				radiusMin = 0.1;
			} else if (duplicatesOfMarker <= 100) {
				radiusInKm = 0.3;
				radiusMin = 0.2;
			} else if (duplicatesOfMarker <= 200) {
				radiusInKm = 0.4;
				radiusMin = 0.2;
			} else {
				radiusInKm = 0.5;
				radiusMin = 0.2;
			}

			double degreePerMarker = 360.0 / duplicatesOfMarker;

			for (double degreeOfMarker = degreePerMarker; degreeOfMarker <= 360.0; degreeOfMarker += degreePerMarker) {

				radiusInKm = Math.random() * (radiusInKm - radiusMin);
				LatLng calculatedPoints = MapHelper.destinationPoint(lat, lon,
						degreeOfMarker, radiusInKm);

				for (MapMarker mapMarker : mapMarkers) {
					if (mapMarker.equals(duplicteMarker)) {
						if (!mapMarker.isCalculatedLatLng()) {
							mapMarker.setCalculatedLatLng(calculatedPoints);
							mapMarker.setCalculatedLatLng(true);
							break;
						}
					}
				}
			}

		}

	}

	@Override
	protected void onProgressUpdate(Integer... values) {

		super.onProgressUpdate(values);

		if (values[0] == 30) {
			progressDialog.setMessage(this.screen.getResources().getString(
					R.string.getting_locations));
		}
	}

	protected void onPostExecute(Integer result) {

		super.onPostExecute(result);

		progressDialog.dismiss();
		progressDialog = null;

		switch (result) {
		case NO_BUSINESS:
			this.screen.showAlert(this.screen
					.getString(R.string.no_business_found));
			// txtErrorLogin.setText(getString(R.string.no_business_found));
			// txtErrorLogin.setVisibility(View.VISIBLE);
			break;

		case CONNECT_ERROR:
			this.screen.showAlert(Messages.CONNECT_ERROR);
			// txtErrorLogin.setText(Messages.CONNECT_ERROR);
			// txtErrorLogin.setVisibility(View.VISIBLE);
			break;

		case SWITCH_SCREEN:

			searchContext.startIndex += searchContext.pageSize;

			if (searchContext.startIndex > (searchContext.totaCount - 1)) {
				searchContext.startIndex = searchContext.totaCount - 1;
			}

			searchComplete.onComplete(this.mapMarkers);

			break;
		case NO_INTERNET_CONNECTION:
			this.screen.showAlert(Messages.NO_INTERNET_CONNECTION);
			// txtErrorLogin.setText(Messages.NO_INTERNET_CONNECTION);
			// txtErrorLogin.setVisibility(View.VISIBLE);
			break;

		}

	}

	protected void onPreExecute() {

		super.onPreExecute();
		// searchContext.keyword = "yahya";
		// txtErrorLogin.setVisibility(View.INVISIBLE);
		if (searchContext.country.length() == 0
				&& searchContext.zip.length() == 0
				&& searchContext.state.length() == 0
				&& searchContext.city.length() == 0
				&& searchContext.keyword.length() == 0) {

			cancel(true);
			return;
		}

		progressDialog = ProgressDialog.show(this.screen, "", "Searching...");

	}

	public static interface SearchComplete {

		void onComplete(List<MapMarker> mapMarkers);

	}

	static final class SearchContext {
		public String keyword = "";
		public String country = "";
		public String zip = "";
		public String state = "";
		public String city = "";
		public int startIndex = 0;

		public int pageSize = 20;
		public int totaCount = 0;

	}

	public static class IconDownloadTask extends
			AsyncTask<CustomAdapterUserList, CustomAdapterUserList, String> {
		@Override
		protected void onProgressUpdate(CustomAdapterUserList... values) {
			// TODO Auto-generated method stub
			super.onProgressUpdate(values);
			values[0].notifyDataSetChanged();

		}

		@Override
		protected String doInBackground(CustomAdapterUserList... params) {
			if (params.length == 1) {
				CustomAdapterUserList adapter = params[0];
				int iteration = 0;
				int refreshInterval = 5;
				try {
					for (MapMarker marker : adapter.getData()) {

						String imageUrl = marker.getIconUrl();
						try {
							if (null != imageUrl && imageUrl.length() > 0) {

								String outputfile = Helper.getTempFile(Helper
										.getHashNameFromUrl(imageUrl) + "");
								if (!new File(outputfile).exists())
									Helper.downloadFile(imageUrl, outputfile);

								boolean exist = MapLogin.getUserListIcons()
										.containsKey(imageUrl);
								if (exist) {

									Bitmap b = MapLogin.getUserListIcons().get(
											imageUrl);
									marker.setIconBitmap(b);
								} else {

									Bitmap b = Helper
											.decode70x70(outputfile, 3);
									MapLogin.getUserListIcons()
											.put(imageUrl, b);
									marker.setIconBitmap(b);
								}

							}
							iteration++;

							if (iteration % refreshInterval == 0) {
								this.publishProgress(adapter);

							}

						} catch (ConcurrentModificationException e) {
							e.printStackTrace();
						}

					}
				} catch (Exception e) {
					// TODO: handle exception
				}

			}

			return null;
		}
	}
}